package com.dl698.sessionlayer.hdlc;

import com.dl698.util.DataUtils;

/**
 * HDLC地址类
 * 实现HDLC地址的编码和解码
 * 
 * @author wind
 * @version 1.1.1
 */
public class HdlcAddress {

    private int byteLength = 0;
    private int logicalDeviceAddress = 0;
    private String physicalDeviceAddress = "";

    /**
     * 构造函数
     * 
     * @param logicalDeviceAddress  逻辑设备地址
     * @param physicalDeviceAddress 物理设备地址
     */
    public HdlcAddress(int logicalDeviceAddress, String physicalDeviceAddress) {
        this.byteLength = physicalDeviceAddress.length() % 2 == 0 ? physicalDeviceAddress.length() / 2
                : (physicalDeviceAddress.length() + 1) / 2;
        ++this.byteLength;
        this.logicalDeviceAddress = logicalDeviceAddress;
        this.physicalDeviceAddress = physicalDeviceAddress;
    }

    /**
     * 获取逻辑设备地址
     * 
     * @return 逻辑设备地址
     */
    public int getLogicalDeviceAddress() {
        return logicalDeviceAddress;
    }

    /**
     * 获取地址类型
     * 
     * @return 地址类型
     */
    public int getAddressType() {
        return (logicalDeviceAddress >> 6) & 0x3;
    }

    /**
     * 设置地址类型
     * 
     * @param addressType 地址类型
     */
    public void setAddressType(int addressType) {
        logicalDeviceAddress = (logicalDeviceAddress & 0x3F) | ((addressType & 0x3) << 6);
    }

    /**
     * 获取物理设备地址
     * 
     * @return 物理设备地址
     */
    public String getPhysicalDeviceAddress() {
        return physicalDeviceAddress;
    }

    /**
     * 获取字节长度
     * 
     * @return 字节长度
     */
    public int getByteLength() {
        return byteLength;
    }

    /**
     * 解码HDLC地址
     * 
     * @param data 地址数据
     * @return HDLC地址对象
     */
    public static HdlcAddress decode(byte[] data) {
        int logicalDeviceAddr;
        String physicalDevAddr;
        logicalDeviceAddr = data[0] & 0x30;
        int addlen = (data[0] & 0xF) + 1;
        physicalDevAddr = DataUtils.toShortHexString(data, 1, addlen, true);
        return new HdlcAddress(logicalDeviceAddr, physicalDevAddr);
    }

    /**
     * 编码HDLC地址
     * 
     * @return 编码后的字节数组
     */
    public byte[] encode() {
        int firstaddr;
        byte[] result = new byte[byteLength];
        firstaddr = logicalDeviceAddress & 0xF0;
        firstaddr = firstaddr | (byteLength - 2) & 0xF;
        result[0] = (byte) firstaddr;

        String physAddr = physicalDeviceAddress;
        if (physAddr.length() % 2 == 1) {
            physAddr += "F";
        }

        byte[] srvaddr = DataUtils.fromShortHexString(physAddr, true);
        System.arraycopy(srvaddr, 0, result, 1, Math.min(srvaddr.length, result.length - 1));
        return result;
    }

    @Override
    public String toString() {
        return String.format("%02X:%s", logicalDeviceAddress, physicalDeviceAddress);
    }
}